const fs = require('fs');
const path = require('path');

const MODULE_ROOT = path.resolve(__dirname, 'src/modules');

const baseImports = `
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { BaseService } from '../../common/base/service';
`;

const baseControllerImports = `
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common';
import { PaginationResult } from '../../common/interface/pagination.interface';
import { ApiTags } from '@nestjs/swagger';
`;

function pascalCase(str) {
  return str.replace(/(^\w|-\w)/g, clearAndUpper);
  function clearAndUpper(text) {
    return text.replace(/-/, '').toUpperCase();
  }
}

function generateEntity(moduleName) {
  const className = pascalCase(moduleName) + 'Entity';
  return `import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm';

@Entity('${moduleName}')
export class ${className} {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 50, comment: '${moduleName}名称' })
  name: string;

  @CreateDateColumn({ comment: '创建时间' })
  createdAt: Date;

  @UpdateDateColumn({ comment: '更新时间' })
  updatedAt: Date;
}
`;
}

function generateCreateDto(moduleName) {
  const className = 'Create' + pascalCase(moduleName) + 'Dto';
  return `import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
  export class ${className} {
  name: string;
}
`;
}

function generateUpdateDto(moduleName) {
  const createDtoName = 'Create' + pascalCase(moduleName) + 'Dto';
  const className = 'Update' + pascalCase(moduleName) + 'Dto';
  return `import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
  import { PartialType } from '@nestjs/mapped-types';
import { ${createDtoName} } from './create-${moduleName}.dto';

export class ${className} extends PartialType(${createDtoName}) {}
`;
}

function generateQueryDto(moduleName) {
  const className = 'Query' + pascalCase(moduleName) + 'Dto';
  return `import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
import { PaginationDto } from '../../../common/dto/pagination.dto';

export class ${className} extends PaginationDto {
  @ApiPropertyOptional({ description: '${moduleName}名称模糊查询' })
  @IsOptional()
  @IsString()
  name?: string;
}
`;
}

function generateService(moduleName) {
  const className = pascalCase(moduleName) + 'Service';
  const entityName = pascalCase(moduleName) + 'Entity';
  const createDto = 'Create' + pascalCase(moduleName) + 'Dto';
  const updateDto = 'Update' + pascalCase(moduleName) + 'Dto';
  const queryDto = 'Query' + pascalCase(moduleName) + 'Dto';

  return `${baseImports}
import { ${entityName} } from './entities/${moduleName}.entity';
import { ${createDto} } from './dto/create-${moduleName}.dto';
import { ${updateDto} } from './dto/update-${moduleName}.dto';
import { ${queryDto} } from './dto/query-${moduleName}.dto';

@Injectable()
export class ${className} extends BaseService<${entityName}> {
  constructor(
    @InjectRepository(${entityName}) private repo: Repository<${entityName}>,
  ) {
    super(repo);
  }

  async create(createDto: ${createDto}): Promise<${entityName}> {
    const exist = await this.repo.findOne({ where: { name: createDto.name } });
    if (exist) {
      throw new NotFoundException(\`${moduleName}已存在\`);
    }
    return this.repo.save(createDto);
  }

  async findAll(query: ${queryDto}) {
    return this.paginate(query, [], [], { id: 'DESC' });
  }

  async findOne(id: number): Promise<${entityName}> {
    const item = await this.repo.findOne({ where: { id } });
    if (!item) {
      throw new NotFoundException(\`未找到id为\${id}的${moduleName}\`);
    }
    return item;
  }

  async update(id: number, updateDto: ${updateDto}): Promise<${entityName}> {
    const item = await this.findOne(id);
    Object.assign(item, updateDto);
    return this.repo.save(item);
  }

  async remove(id: number) {
    const res = await this.repo.delete(id);
    if (res.affected === 0) {
      throw new NotFoundException(\`未找到id为\${id}的${moduleName}\`);
    }
    return { message: '${moduleName}已删除' };
  }
}
`;
}

function generateController(moduleName) {
  const className = pascalCase(moduleName) + 'Controller';
  const serviceName = pascalCase(moduleName) + 'Service';
  const createDto = 'Create' + pascalCase(moduleName) + 'Dto';
  const updateDto = 'Update' + pascalCase(moduleName) + 'Dto';
  const queryDto = 'Query' + pascalCase(moduleName) + 'Dto';
  const entityName = pascalCase(moduleName) + 'Entity';

  return `${baseControllerImports}
import { ${serviceName} } from './${moduleName}.service';
import { ${createDto} } from './dto/create-${moduleName}.dto';
import { ${updateDto} } from './dto/update-${moduleName}.dto';
import { ${queryDto} } from './dto/query-${moduleName}.dto';
import { ${entityName} } from './entities/${moduleName}.entity';
import { ApiOperation } from '@nestjs/swagger'
import { UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Public } from '../auth/auth.decorator';//JWT校验白名单装饰器

@ApiTags('${moduleName}')
@Controller('${moduleName}')
export class ${className} {
  constructor(private readonly service: ${serviceName}) {}

  @Post()
  @ApiOperation({ summary: '创建${moduleName}' })
  create(@Body() createDto: ${createDto}) {
    return this.service.create(createDto);
  }

  @Get()
  @ApiOperation({ summary: '获取${moduleName}列表' })
  async findAll(@Query() query: ${queryDto}): Promise<PaginationResult<${entityName}>> {
    return this.service.findAll(query);
  }

  @Get(':id')
  @ApiOperation({ summary: '根据ID获取${moduleName}' })
  findOne(@Param('id') id: number) {
    return this.service.findOne(+id);
  }

  @Patch(':id')
  @ApiOperation({ summary: '更新${moduleName}' })
  update(@Param('id') id: number, @Body() updateDto: ${updateDto}) {
    return this.service.update(+id, updateDto);
  }

  @Delete(':id')
  @ApiOperation({ summary: '删除${moduleName}' })
  remove(@Param('id') id: number) {
    return this.service.remove(+id);
  }
}
`;
}

function generateModuleTs(moduleName) {
  const pascal = pascalCase(moduleName);
  return `import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ${pascal}Service } from './${moduleName}.service';
import { ${pascal}Controller } from './${moduleName}.controller';
import { ${pascal}Entity } from './entities/${moduleName}.entity';

@Module({
  imports: [TypeOrmModule.forFeature([${pascal}Entity])],
  controllers: [${pascal}Controller],
  providers: [${pascal}Service],
})
export class ${pascal}Module {}
`;
}

function makeDirIfNotExist(dir) {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
}

function generateModule(moduleName) {
  const moduleDir = path.join(MODULE_ROOT, moduleName);
  const entitiesDir = path.join(moduleDir, 'entities');
  const dtoDir = path.join(moduleDir, 'dto');

  makeDirIfNotExist(moduleDir);
  makeDirIfNotExist(entitiesDir);
  makeDirIfNotExist(dtoDir);

  fs.writeFileSync(path.join(entitiesDir, `${moduleName}.entity.ts`), generateEntity(moduleName));
  fs.writeFileSync(path.join(dtoDir, `create-${moduleName}.dto.ts`), generateCreateDto(moduleName));
  fs.writeFileSync(path.join(dtoDir, `update-${moduleName}.dto.ts`), generateUpdateDto(moduleName));
  fs.writeFileSync(path.join(dtoDir, `query-${moduleName}.dto.ts`), generateQueryDto(moduleName));
  fs.writeFileSync(path.join(moduleDir, `${moduleName}.service.ts`), generateService(moduleName));
  fs.writeFileSync(path.join(moduleDir, `${moduleName}.controller.ts`), generateController(moduleName));
  fs.writeFileSync(path.join(moduleDir, `${moduleName}.module.ts`), generateModuleTs(moduleName));

  console.log(`模块 ${moduleName} 生成完成！路径：${moduleDir}`);
}

// 入口：从命令行参数获取模块名
const modules = process.argv.slice(2);

if (modules.length === 0) {
  console.error('请传入至少一个模块名，例如：node generate-modules.js user role department');
  process.exit(1);
}

modules.forEach(generateModule);